/**
 * Copyright 2019 Anthony Trinh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ch.qos.logback.classic;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;

import java.util.List;
import java.util.Map;

import org.junit.Ignore;
import org.junit.Test;

import ch.qos.logback.classic.control.ControlLogger;
import ch.qos.logback.classic.control.ControlLoggerContext;
import ch.qos.logback.classic.control.CreateLogger;
import ch.qos.logback.classic.control.ScenarioAction;
import ch.qos.logback.classic.control.ScenarioMaker;
import ch.qos.logback.classic.control.SetLevel;
import ch.qos.logback.classic.control.Scenario;


public class ScenarioBasedLoggerContextTest  {
  LoggerContext lc;

  
  @Test
  public void testLen3() {
    doScenarioedTest(3);
  }

  @Test
  public void testLength_30() {
    doScenarioedTest(30);
  }

  @Test
  public void testLength_20000() {
    doScenarioedTest(20*1000);
  }

  @Test
  @Ignore
  public void testLengthLong() {
    doScenarioedTest(100*1000);
  }

  private void doScenarioedTest(int len) {
    LoggerContext lc = new LoggerContext();
    ControlLoggerContext controlContext = new ControlLoggerContext();
    Scenario s = ScenarioMaker.makeRealisticCreationScenario(len);
    List<ScenarioAction> actionList = s.getActionList();
    int size = actionList.size();
    for (int i = 0; i < size; i++) {
      ScenarioAction action = (ScenarioAction) actionList.get(i);
      if (action instanceof CreateLogger) {
        CreateLogger cl = (CreateLogger) action;
        lc.getLogger(cl.getLoggerName());
        controlContext.getLogger(cl.getLoggerName());
      } else if (action instanceof SetLevel) {
        SetLevel sl = (SetLevel) action;
        Logger l = lc.getLogger(sl.getLoggerName());
        ControlLogger controlLogger = controlContext.getLogger(sl.getLoggerName());
        l.setLevel(sl.getLevel());
        controlLogger.setLevel(sl.getLevel());
      }
    }

    compareLoggerContexts(controlContext, lc);
  }

  void compareLoggerContexts(ControlLoggerContext controlLC, LoggerContext lc) {
    Map<String, ControlLogger> controlLoggerMap = controlLC.getLoggerMap();

    assertEquals(controlLoggerMap.size()+1, lc.size());

    for (String loggerName: controlLoggerMap.keySet()) {
        
      Logger logger = lc.exists(loggerName);
      ControlLogger controlLogger = (ControlLogger) controlLoggerMap.get(loggerName);
      if (logger == null) {
        throw new IllegalStateException("logger" + loggerName + " should exist");
      }
      assertEquals(loggerName, logger.getName());
      assertEquals(loggerName, controlLogger.getName());

      compareLoggers(controlLogger, logger);
    }
  }

  void compareLoggers(ControlLogger controlLogger, Logger logger) {
    assertEquals(controlLogger.getName(), logger.getName());
    assertEquals(controlLogger.getEffectiveLevel(), logger.getEffectiveLevel());

    Level controlLevel = controlLogger.getLevel();
    Level level = logger.getLevel();

    if (controlLevel == null) {
      assertNull(level);
    } else {
      assertEquals(controlLevel, level);
    }
  }
}